package com.chuanyun.wechatcheckin.service;

import com.chuanyun.wechatcheckin.model.wechat.VacationInfo;
import com.chuanyun.wechatcheckin.model.wechat.VacationQuotaResponse;
import com.chuanyun.wechatcheckin.model.VacationQuotaRequest;
import com.chuanyun.wechatcheckin.model.VacationQuotaUpdateResponse;
import com.chuanyun.wechatcheckin.model.h3yun.H3yunResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 调休申请处理服务
 * 处理氚云调休申请数据，自动更新企业微信假期余额
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BalanceLeaveProcessService {

    private final H3yunApiService h3yunApiService;
    private final VacationService vacationService;
    private final VacationManagementService vacationManagementService;

    // 氚云表配置
    private static final String OVERTIME_TABLE_SCHEMA_CODE = "D290920sjxsawd7uuw5tupspi71";
    private static final String LEAVE_TYPE_FIELD = "F0000012";  // 申请类型控件
    private static final String TEMP_TIME_FIELD = "F0000010";   // 调休时长控件
    private static final String USER_ID_FIELD = "userId";       // 用户ID控件
    
    // 企业微信假期配置
    private static final String BALANCE_LEAVE_NAME = "Balance Leave  调休假";
    private static final String BALANCE_LEAVE_TYPE = "Balance Leave 申请调休";
    private static final int VACATION_ID = 4;  // 调休假期ID
    private static final int TIME_ATTR = 0;   // 按天请假（必须为8640整倍数，即0.1天整倍数，8640秒=0.1天）
    
    // 氚云记录状态更新配置
    private static final String UPDATE_STATUS_FIELD = "UpDate";  // 更新状态控件
    private static final String UPDATED_STATUS_VALUE = "已更新";  // 已更新状态值

    /**
     * 处理调休申请数据
     * 自动化处理流程：查询氚云表 -> 获取企业微信假期余额 -> 更新假期余额 -> 更新氚云记录状态
     */
    public void processBalanceLeaveApplications() {
        log.info("开始处理调休申请数据...");
        
        try {
            // 1. 查询氚云表中的调休申请数据
            List<Map<String, Object>> balanceLeaveRecords = queryBalanceLeaveRecords();
            
            if (balanceLeaveRecords.isEmpty()) {
                log.info("未找到需要处理的调休申请记录");
                return;
            }
            
            log.info("找到 {} 条调休申请记录，开始处理", balanceLeaveRecords.size());
            
            // 2. 逐条处理调休申请
            int successCount = 0;
            int failCount = 0;
            
            for (Map<String, Object> record : balanceLeaveRecords) {
                try {
                    boolean result = processSingleBalanceLeaveRecord(record);
                    if (result) {
                        successCount++;
                    } else {
                        failCount++;
                    }
                } catch (Exception e) {
                    log.error("处理调休申请记录失败: {}", record, e);
                    failCount++;
                }
            }
            
            log.info("调休申请处理完成，成功: {} 条，失败: {} 条", successCount, failCount);
            
        } catch (Exception e) {
            log.error("处理调休申请数据时发生异常", e);
            throw new RuntimeException("处理调休申请数据失败", e);
        }
    }

    /**
     * 查询氚云表中的调休申请记录（支持自动分页）
     */
    private List<Map<String, Object>> queryBalanceLeaveRecords() throws Exception {
        log.info("查询氚云表中的调休申请记录，表编码: {}", OVERTIME_TABLE_SCHEMA_CODE);
        
        // 构建查询条件：F0000012 = "Balance Leave 申请调休"
        List<Map<String, Object>> matchers = new ArrayList<>();
        Map<String, Object> leaveTypeMatcher = new HashMap<>();
        leaveTypeMatcher.put("PropertyCode", LEAVE_TYPE_FIELD);
        leaveTypeMatcher.put("PropertyValue", BALANCE_LEAVE_TYPE);
        leaveTypeMatcher.put("Type", "Equal");
        matchers.add(leaveTypeMatcher);
        
        // 指定返回字段
        List<String> returnItems = new ArrayList<>();
        returnItems.add(LEAVE_TYPE_FIELD);  // 申请类型
        returnItems.add(TEMP_TIME_FIELD);   // 调休时长
        returnItems.add(USER_ID_FIELD);     // 用户ID
        returnItems.add("ObjectId");        // 记录ID
        returnItems.add(UPDATE_STATUS_FIELD); // 更新状态字段
        
        // 自动分页查询所有数据
        List<Map<String, Object>> allRecords = new ArrayList<>();
        int pageSize = 100;  // 每页查询100条
        int pageIndex = 0;   // 从第0页开始
        boolean hasMoreData = true;
        
        while (hasMoreData) {
            log.info("查询第 {} 页数据，每页 {} 条", pageIndex + 1, pageSize);
            
            H3yunResponse<Object> response = h3yunApiService.queryBizDataWithConditions(
                OVERTIME_TABLE_SCHEMA_CODE, pageIndex, pageSize, returnItems, matchers);
            
            if (!response.isSuccess()) {
                log.error("查询氚云调休申请数据失败: {}", response.getErrorMessage());
                throw new RuntimeException("查询氚云数据失败: " + response.getErrorMessage());
            }
            
            List<Map<String, Object>> pageRecords = parseH3yunResponseData(response.getReturnData());
            
            if (pageRecords.isEmpty()) {
                // 当前页没有数据，结束分页查询
                hasMoreData = false;
                log.info("第 {} 页无数据，分页查询结束", pageIndex + 1);
            } else {
                // 添加当前页数据到总结果集
                allRecords.addAll(pageRecords);
                log.info("第 {} 页查询到 {} 条记录，累计 {} 条", pageIndex + 1, pageRecords.size(), allRecords.size());
                
                // 如果当前页数据少于页大小，说明已经是最后一页
                if (pageRecords.size() < pageSize) {
                    hasMoreData = false;
                    log.info("当前页数据量 {} < 页大小 {}，已到最后一页", pageRecords.size(), pageSize);
                } else {
                    // 继续查询下一页
                    pageIndex++;
                }
            }
        }
        
        log.info("分页查询完成，总共查询到 {} 条调休申请记录", allRecords.size());
        return allRecords;
    }

    /**
     * 处理单条调休申请记录
     */
    private boolean processSingleBalanceLeaveRecord(Map<String, Object> record) {
        try {
            // 提取记录信息
            String objectId = getStringValue(record, "ObjectId");
            String leaveType = getStringValue(record, LEAVE_TYPE_FIELD);
            String tempTimeStr = getStringValue(record, TEMP_TIME_FIELD);
            String userId = getStringValue(record, USER_ID_FIELD);
            String UpDate = getStringValue(record, UPDATE_STATUS_FIELD);
            
            // 检查更新状态，如果已更新则跳过处理
            if (UPDATED_STATUS_VALUE.equals(UpDate)) {
                log.info("记录已处理过，跳过 - ObjectId: {}", objectId);
                return true; // 返回true表示处理成功（已跳过）
            }
            
            log.info("处理调休申请 - ObjectId: {}, UserId: {}, 时长: {}小时", objectId, userId, tempTimeStr);
            
            // 验证必要字段
            if (!BALANCE_LEAVE_TYPE.equals(leaveType)) {
                log.warn("跳过非调休申请记录: {}", leaveType);
                return false;
            }
            
            if (userId == null || userId.trim().isEmpty()) {
                log.error("用户ID为空，跳过处理");
                return false;
            }
            
            if (tempTimeStr == null || tempTimeStr.trim().isEmpty()) {
                log.error("调休时长为空，跳过处理");
                return false;
            }
            
            // 解析调休时长（小时）
            double tempTimeHours;
            try {
                tempTimeHours = Double.parseDouble(tempTimeStr);
            } catch (NumberFormatException e) {
                log.error("调休时长格式错误: {}", tempTimeStr);
                return false;
            }
            
            if (tempTimeHours <= 0) {
                log.warn("调休时长必须大于0，当前值: {}", tempTimeHours);
                return false;
            }
            
            // 获取企业微信假期余额
            VacationQuotaResponse vacationResponse = vacationService.getUserVacationQuota(userId);
            if (!vacationResponse.isSuccess()) {
                log.error("获取用户假期余额失败: userId={}, errcode={}, errmsg={}", 
                        userId, vacationResponse.getErrcode(), vacationResponse.getErrmsg());
                return false;
            }
            
            // 查找调休假期类型
            VacationInfo balanceLeaveInfo = findBalanceLeaveVacation(vacationResponse.getLists());
            if (balanceLeaveInfo == null) {
                log.error("未找到调休假期类型: {}", BALANCE_LEAVE_NAME);
                return false;
            }
            
            // 计算新的假期余额（按天请假，必须为8640整倍数，即0.1天整倍数）
            long currentLeftDuration = balanceLeaveInfo.getLeftDuration();
            
            // 将小时数转换为秒，然后对除以8640后的数值向下取整
            long tempTimeSeconds = (long) (tempTimeHours * 3600); // 小时转秒
            long tempTime8640Units = (long) Math.floor(tempTimeSeconds / 8640.0); // 对除以8640后的数值向下取整（0.1天单位）
            long actualTempTimeSeconds = tempTime8640Units * 8640; // 实际增加的秒数
            long newLeftDuration = currentLeftDuration + actualTempTimeSeconds;
            
            log.info("假期余额更新 - 当前: {}秒, 增加: {}小时, 新余额: {}秒", currentLeftDuration, tempTimeHours, newLeftDuration);
            
            // 调用修改假期余额接口
            VacationQuotaRequest updateRequest = new VacationQuotaRequest();
            updateRequest.setUserid(userId);
            updateRequest.setVacation_id(VACATION_ID);
            updateRequest.setLeftduration(newLeftDuration);
            updateRequest.setTime_attr(TIME_ATTR);
            updateRequest.setRemarks("系统自动处理调休申请，增加" + tempTimeHours + "小时，8640取整后增加" + tempTime8640Units + "个0.1天单位(" + (actualTempTimeSeconds/3600.0) + "小时)调休余额");
            
            VacationQuotaUpdateResponse updateResponse = vacationManagementService.updateUserVacationQuota(updateRequest);
            if (!updateResponse.isSuccess()) {
                log.error("更新假期余额失败: userId={}, errcode={}, errmsg={}", 
                        userId, updateResponse.getErrcode(), updateResponse.getErrmsg());
                return false;
            }
            
            log.info("调休申请处理成功 - UserId: {}, 增加: {}小时", userId, tempTimeHours);
            
            // 只有在成功更新企业微信假期余额后，才更新氚云记录状态为"已更新"
            updateH3yunRecordStatus(objectId);
            
            return true;
            
        } catch (Exception e) {
            log.error("处理调休申请记录时发生异常: {}", record, e);
            return false;
        }
    }

    /**
     * 查找调休假期类型
     */
    private VacationInfo findBalanceLeaveVacation(List<VacationInfo> vacationList) {
        if (vacationList == null || vacationList.isEmpty()) {
            return null;
        }
        
        for (VacationInfo vacation : vacationList) {
            if (BALANCE_LEAVE_NAME.equals(vacation.getVacationName())) {
                return vacation;
            }
        }
        
        return null;
    }

    /**
     * 解析氚云响应数据
     */
    @SuppressWarnings("unchecked")
    private List<Map<String, Object>> parseH3yunResponseData(Object returnData) {
        if (returnData == null) {
            return new ArrayList<>();
        }
        
        if (returnData instanceof List) {
            return (List<Map<String, Object>>) returnData;
        } else if (returnData instanceof Map) {
            Map<String, Object> dataMap = (Map<String, Object>) returnData;
            Object bizObjectArray = dataMap.get("BizObjectArray");
            if (bizObjectArray instanceof List) {
                return (List<Map<String, Object>>) bizObjectArray;
            }
        }
        
        return new ArrayList<>();
    }

    /**
     * 安全获取字符串值
     */
    private String getStringValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? value.toString().trim() : null;
    }

    /**
     * 更新氚云记录状态为"已更新"
     */
    private void updateH3yunRecordStatus(String objectId) {
        try {
            if (objectId == null || objectId.trim().isEmpty()) {
                log.warn("ObjectId为空，无法更新氚云记录状态");
                return;
            }
            
            // 构建更新数据
            Map<String, Object> updateData = new HashMap<>();
            updateData.put(UPDATE_STATUS_FIELD, UPDATED_STATUS_VALUE);
            
            log.info("开始更新氚云记录状态 - ObjectId: {}, 状态: {}", objectId, UPDATED_STATUS_VALUE);
            
            // 调用氚云更新API
            h3yunApiService.updateBizObject(
                OVERTIME_TABLE_SCHEMA_CODE,  // 表单编码
                objectId,                    // 业务对象ID
                updateData,                  // 更新数据
                false                        // 不提交，只保存
            );
            
            log.info("成功更新氚云记录状态 - ObjectId: {}", objectId);
            
        } catch (Exception e) {
            log.error("更新氚云记录状态失败 - ObjectId: {}", objectId, e);
            // 不抛出异常，避免影响主流程
        }
    }
}